package com.ruoyi.odorservice.controller;


import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.Result;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.odorservice.entity.*;
import com.ruoyi.odorservice.entity.model.MaterialTypeValue;
import com.ruoyi.odorservice.entity.model.SampleDetailWithMaterial;
import com.ruoyi.odorservice.entity.model.SiteMaterial;
import com.ruoyi.odorservice.entity.model.SourceMedol;
import com.ruoyi.odorservice.entity.vo.*;
import com.ruoyi.odorservice.model.vo.SiteMatchDegree;
import com.ruoyi.odorservice.service.*;
import com.ruoyi.odorservice.utils.ExcelUtils;
import com.ruoyi.odorservice.utils.VectorUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 污染源-工艺过程 前端控制器
 * </p>
 *
 * @author mybatis-plus
 * @since 2024-12-01
 */
@Slf4j
@RestController
@RequestMapping("/source")
@Api(tags = "污染源")
@AllArgsConstructor
public class SourceController extends BaseController {

    private SourceEnterpriseService sourceEnterpriseService;
    private SourceService sourceService;
    private SourceOdorService odorService;
    private MaterialService materialService;
    private SampleService sampleService;
    private SampleDetailService sampleDetailService;
    @GetMapping("/odorList")
    @ApiOperation(value = "污染源臭气浓度", httpMethod = "GET", response = StandardFiles.class)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "siteName", value = "源编号 如：BH", paramType = "query", dataType = "String", required = false)
    })
    public List<SourceOdor> odorList(@RequestParam(value = "siteName", required = false) String siteName) {
        List<SourceOdor> list = odorService.list(new LambdaQueryWrapper<SourceOdor>()
                .eq(StrUtil.isNotEmpty(siteName), SourceOdor::getSiteName, siteName)
        );
        return list;
    }


    @PostMapping("/delete/{id}")
    @ApiOperation(value = "删除企业", httpMethod = "POST", response = StandardFiles.class)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "企业ID", paramType = "path", dataType = "Integer")
    })
    public Result delete(@PathVariable(value = "id") Integer id) {
        if (sourceEnterpriseService.removeById(id)) {
            sourceService.remove(new LambdaQueryWrapper<Source>()
                    .eq(Source::getEnvironmentalControlFacilities, id));
            return Result.ok();
        } else
            return Result.fail();
    }

    @PostMapping("/update/source/{id}")
    @ApiOperation(value = "更新污染源信息", httpMethod = "POST", response = StandardFiles.class)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "ID", paramType = "path", dataType = "Integer")
    })
    public Result update(@PathVariable(value = "id") Integer id,
                         @RequestBody Source source) {
        source.setId(id);
        assert source.getEnterpriseId() != null;
        if (sourceService.updateById(source))
            return Result.ok();
        else
            return Result.fail();
    }
    @PostMapping("/add/source")
    @ApiOperation(value = "新增", httpMethod = "POST", response = StandardFiles.class)
    public Result add(@RequestBody Source source) {
        if (sourceService.updateById(source))
            return Result.ok();
        else
            return Result.fail();
    }
    @GetMapping("/pages")
    @ApiOperation(value = "污染源企业列表", httpMethod = "GET", response = StandardFiles.class)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "page", value = "页码", paramType = "query", dataType = "Integer", required = false),
            @ApiImplicitParam(name = "limit", value = "每页数量", paramType = "query", dataType = "Integer", required = false),
            @ApiImplicitParam(name = "sourceName", value = "企业名称", paramType = "query", dataType = "String", required = false),
            @ApiImplicitParam(name = "sourceCode", value = "代码", paramType = "query", dataType = "String", required = false),
    })
    public TableDataInfo pages(@RequestParam(value = "page", defaultValue = "1", required = false) Integer page,
                               @RequestParam(value = "limit", defaultValue = "10", required = false) Integer limit,
                               @RequestParam(value = "sourceName", required = false) String sourceName,
                               @RequestParam(value = "sourceCode", required = false) String sourceCode) {
        startPage();
        List<SourceEnterprise> list = sourceEnterpriseService.list(new LambdaQueryWrapper<SourceEnterprise>()
                .like(StrUtil.isNotEmpty(sourceName), SourceEnterprise::getSourceName, sourceName)
                .eq(StrUtil.isNotEmpty(sourceCode), SourceEnterprise::getSourceCode, sourceCode)
        );
        return getDataTable(list);
    }

    @GetMapping("details/pages")
    @ApiOperation(value = "污染源详情(工艺)", httpMethod = "GET", response = StandardFiles.class)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "page", value = "页码", paramType = "query", dataType = "Integer", required = false),
            @ApiImplicitParam(name = "limit", value = "每页数量", paramType = "query", dataType = "Integer", required = false),
            @ApiImplicitParam(name = "enterpriseId", value = "污染源（企业）ID", paramType = "query", dataType = "String", required = false)
    })
    public TableDataInfo details(@RequestParam(value = "page", defaultValue = "1", required = false) Integer page,
                                 @RequestParam(value = "limit", defaultValue = "10", required = false) Integer limit,
                                 @RequestParam(value = "enterpriseId", required = false) Integer enterpriseId) {
        startPage();
        List<Source> list = sourceService.list(new LambdaQueryWrapper<Source>()
                .eq(enterpriseId != null, Source::getEnterpriseId, enterpriseId));
        return getDataTable(list);
    }

    @ApiOperation(value = "上传样本", httpMethod = "POST", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "file", paramType = "form", value = "文件", dataType = "file", required = true),
    })
    @PostMapping(value = "/importExcel")
    @ResponseBody
    public Result importExcel(@RequestPart @RequestParam("file") MultipartFile file) {
        try (InputStream inputStream = file.getInputStream()) {
            Map<String, String[][]> map = ExcelUtils.readExcel(inputStream);
            assert map != null;
            map.forEach((k, v) -> {
                for (int i = 2; i < v.length; i++) {
                    for (int j = 0; j < v[0].length; j++) {
                        if (StrUtil.isBlank(v[i][j])) {
                            v[i][j] = v[i - 1][j];
                        }
                    }
                }
            });
            List<SourceMedol> medols = new ArrayList<>();
            map.forEach((k, v) -> {
                int rows = v.length;
                int cols = (rows > 0) ? v[0].length : 0;
                for (int i = 1; i < rows; i++) {
                    SourceMedol medol = new SourceMedol();
                    for (int j = 0; j < cols; ) {
                        medol.setSourceName(v[i][j++])
                                .setSourceShortName(v[i][j++])
                                .setSourceCode(v[i][j++])
                                .setIndustry(v[i][j++])
                                .setAddress(v[i][j++])
                                .setLongitude(Double.valueOf(v[i][j++]))
                                .setLatitude(Double.valueOf(v[i][j++]))
                                .setMainProduction(v[i][j++])
                                .setSourceType(v[i][j++])
                                .setMainMaterials(v[i][j++])
                                .setSourceCraftName(v[i][j++])
                                .setSiteName(v[i][j++])
                                .setLongitude2(Double.valueOf(v[i][j++]))
                                .setLatitude2(Double.valueOf(v[i][j++]))
                                .setCraftName(v[i][j++])
                                .setEnvironmentalControlFacilities(v[i][j++]);
                    }
                    medols.add(medol);
                }
            });
            Map<String, List<SourceMedol>> listMap = medols.stream().collect(Collectors.groupingBy(SourceMedol::getSourceName));
            listMap.forEach((k, v) -> {
                SourceEnterprise enterprise = new SourceEnterprise();
                BeanUtils.copyProperties(v.get(0), enterprise);
                enterprise.setCreateTime(LocalDateTime.now());
                sourceEnterpriseService.save(enterprise);
                v.forEach(s -> {
                    Source source = new Source();
                    BeanUtils.copyProperties(s, source);
                    source.setEnterpriseId(enterprise.getId());
                    source.setSourceName(s.getSourceCraftName());
                    source.setLatitude(s.getLatitude2());
                    source.setLongitude(s.getLongitude2());
                    source.setCreateTime(LocalDateTime.now());
                    sourceService.save(source);
                });
            });
            return Result.ok("上传成功！");
        } catch (IOException e) {
            return Result.fail("上传失败！");
        }
    }

    @GetMapping("/enterpriseOptions")
    @ApiOperation(value = "企业名称列表", httpMethod = "GET")
    public Result<List<String>> getIndustries() {
        List<SourceEnterprise> industries = sourceEnterpriseService.list(new LambdaQueryWrapper<SourceEnterprise>()
                .select(SourceEnterprise::getSourceName));
        return Result.ok(industries.stream().map(SourceEnterprise::getSourceName).distinct().collect(Collectors.toList()));
    }

    @GetMapping("/siteOptions")
    @ApiOperation(value = "企业点位列表", httpMethod = "GET")
    public Result<List<Source>> getSites() {
        List<SourceEnterprise> industries = sourceEnterpriseService.list(new LambdaQueryWrapper<SourceEnterprise>()
                .select(SourceEnterprise::getId, SourceEnterprise::getSourceShortName));
        if (!industries.isEmpty()) {
            Map<Integer, String> map = industries.stream().collect(Collectors.toMap(SourceEnterprise::getId, SourceEnterprise::getSourceShortName));
            List<Source> sources = sourceService.list(new LambdaQueryWrapper<Source>()
                    .in(Source::getEnterpriseId, industries.stream().map(SourceEnterprise::getId).collect(Collectors.toList())));
            if (!sources.isEmpty()) {
                sources.forEach(s -> {
                    s.setSiteName(map.get(s.getEnterpriseId()) + "_" + s.getSiteName());
                });
                return Result.ok(sources);
            }
        }

        return Result.ok();
    }

    @GetMapping("/analysis/site/one")
    @ApiOperation(value = "单点分析-单点时序分析", httpMethod = "GET", response = SourceOdor.class)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "siteId", value = "点位ID", paramType = "query", dataType = "siteId", required = true)
    })
    public Result getOneSiteAnalysis(@RequestParam(value = "siteId", required = true) String siteId) {
        Source sources = sourceService.getById(siteId);
        if (sources == null)
            return Result.fail("点位ID为空！");
        List<SampleDetailVo> voList = sampleService.getSampleWithMaterialList(sources.getSiteName());
        return Result.ok(voList);
    }

    @GetMapping("/analysis/sites")
    @ApiOperation(value = "单点分析-多点比较分析", httpMethod = "GET", response = SourceOdor.class)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "siteIds", value = "点位ID集合，以逗号隔开", paramType = "query", dataType = "siteIds", required = true)
    })
    public Result getSitesAnalysis(@RequestParam(value = "siteIds", required = true) String siteIds) {
        String[] strings = siteIds.split(",");
        if (strings.length == 0)
            return Result.fail("点位ID为空！");
        List<Source> sources = sourceService.list(new LambdaQueryWrapper<Source>().in(Source::getId, Arrays.stream(siteIds.split(",")).collect(Collectors.toList())));
        if (sources.isEmpty())
            return Result.fail("点位ID为空！");
        List<SiteMaterial> voList = sampleService.getSiteMaterials(sources.stream().map(Source::getSiteName).collect(Collectors.toList()));
        Map<String, List<SiteMaterial>> map = voList.stream().collect(Collectors.groupingBy(SiteMaterial::getSiteName));
        List<SiteMaterialVo> res = new ArrayList<>();
        map.forEach((k, v) -> {
            SiteMaterialVo vo = new SiteMaterialVo();
            vo.setSiteName(k);
            vo.setSiteMaterials(v);
            double pq = v.stream().filter(s -> s.getMaterialName().contains("排气量")).mapToDouble(SiteMaterial::getConcentration).sum();
            vo.setStackVelum(pq);
            //臭气浓度
            double odor = v.stream().filter(s -> s.getMaterialName().contains("臭气浓度")).mapToDouble(SiteMaterial::getConcentration).sum();
            vo.setOdor(odor);

            List<MaterialTypeValue> materialTypeValues = new ArrayList<>();
            double other = v.stream().filter(s -> !s.getMaterialName().contains("臭气") && !s.getMaterialName().contains("排气量") && s.getMaterialType() == null).mapToDouble(SiteMaterial::getConcentration).sum();
            materialTypeValues.add(new MaterialTypeValue("其他", other));
            Map<String, List<SiteMaterial>> m = v.stream().filter(s -> !s.getMaterialName().contains("排气量") && s.getMaterialType() != null).collect(Collectors.groupingBy(SiteMaterial::getMaterialType));
            m.forEach((k1, v1) -> {
                double sum = v1.stream().mapToDouble(SiteMaterial::getConcentration).sum();
                materialTypeValues.add(new MaterialTypeValue(k1, sum));
            });
            vo.setMaterialTypes(materialTypeValues);
            res.add(vo);
        });
        return Result.ok(res);
    }

    @GetMapping("/analysis/sours")
    @ApiOperation(value = "单点分析-企业比较分析", httpMethod = "GET", response = SourceOdor.class)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "sourceIds", value = "源ID集合，以逗号隔开", paramType = "query", dataType = "siteIds", required = true)
    })
    public Result getSoursAnalysis(@RequestParam(value = "sourceIds", required = true) String sourceIds) {
        String[] strings = sourceIds.split(",");
        if (strings.length == 0)
            return Result.fail("源ID为空！");
        List<SourceEnterprise> enterprises = sourceEnterpriseService.list(new LambdaQueryWrapper<SourceEnterprise>().in(SourceEnterprise::getId, Arrays.stream(sourceIds.split(",")).collect(Collectors.toList())));
        if (enterprises.isEmpty())
            return Result.fail("点位ID为空！");
        List<Integer> ids = enterprises.stream().map(SourceEnterprise::getId).collect(Collectors.toList());
        List<SiteMaterial> siteMaterials = sampleService.getMaterialsBySites(ids);
        Map<String, List<SiteMaterial>> map = siteMaterials.stream().collect(Collectors.groupingBy(SiteMaterial::getSourceName));
        List<SiteMaterialVo> res = new ArrayList<>();
        map.forEach((k, v) -> {
            SiteMaterialVo vo = new SiteMaterialVo();
            vo.setSourceName(k);
            vo.setSiteMaterials(v);
            double pq = v.stream().filter(s -> s.getMaterialName().contains("排气量")).mapToDouble(SiteMaterial::getConcentration).sum();
            vo.setStackVelum(pq);
            //臭气浓度
            double odor = v.stream().filter(s -> s.getMaterialName().contains("臭气浓度")).mapToDouble(SiteMaterial::getConcentration).sum();
            vo.setOdor(odor);

            List<MaterialTypeValue> materialTypeValues = new ArrayList<>();
            double other = v.stream().filter(s -> !s.getMaterialName().contains("臭气") && !s.getMaterialName().contains("排气量") && s.getMaterialType() == null).mapToDouble(SiteMaterial::getConcentration).sum();
            materialTypeValues.add(new MaterialTypeValue("其他", other));
            Map<String, List<SiteMaterial>> m = v.stream().filter(s -> !s.getMaterialName().contains("排气量") && s.getMaterialType() != null).collect(Collectors.groupingBy(SiteMaterial::getMaterialType));
            m.forEach((k1, v1) -> {
                double sum = v1.stream().mapToDouble(SiteMaterial::getConcentration).sum();
                materialTypeValues.add(new MaterialTypeValue(k1, sum));
            });
            vo.setMaterialTypes(materialTypeValues);
            res.add(vo);
        });
        return Result.ok(res);
    }

    @GetMapping("/normalize/sites")
    @ApiOperation(value = "因子识别-图谱生成-指纹图谱", httpMethod = "GET", response = SourceOdor.class)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "siteIds", value = "点位ID集合，用逗号隔开", paramType = "query", dataType = "siteIds", required = true)
    })
    public Result<List<SiteSampleVo>> getNormalizedConcentration(@RequestParam(value = "siteIds", required = true) String siteIds) {
        List<Source> sources = sourceService.list(new LambdaQueryWrapper<Source>()
                .in(StrUtil.isNotBlank(siteIds), Source::getId, Arrays.stream(siteIds.split(",")).collect(Collectors.toList())));
        if (sources.isEmpty())
            return Result.fail("点位ID为空！");
        List<SampleVo> sampleVos = new ArrayList<>();
        sources.forEach(s -> {
            List<SampleVo> voList = sampleService.getSampleList(s.getSiteName());
            sampleVos.addAll(voList);
        });
        Map<String, List<SampleVo>> map = sampleVos.stream().collect(Collectors.groupingBy(SampleVo::getSiteName));
        List<SiteSampleVo> res = new ArrayList<>();
        map.forEach((k, v) -> {
            SiteSampleVo siteSampleVo = new SiteSampleVo();
            siteSampleVo.setSiteName(k);

            List<SampleDetail> details = new ArrayList<>();
            v.forEach(s -> {
                details.addAll(s.getSampleDetails());
            });
            Map<String, List<SampleDetail>> sampleMap = details.stream().collect(Collectors.groupingBy(SampleDetail::getMaterialName));
            List<SampleMaterialVo> sampleMaterialVos = new ArrayList<>();
            sampleMap.forEach((k1, v1) -> {
                SampleMaterialVo vo = new SampleMaterialVo();
                vo.setMaterialName(k1);
                vo.setSiteName(k);
                vo.setCasNo(v1.get(0).getCasNo());
                vo.setOav(v1.get(0).getOav());
                vo.setConcentration(v1.stream().mapToDouble(SampleDetail::getConcentration).average().orElse(0));
                sampleMaterialVos.add(vo);
            });
            siteSampleVo.setSampleMaterialVos(sampleMaterialVos);

            res.add(siteSampleVo);
        });
        return Result.ok(res);
    }

    @GetMapping("/enterprise/odors")
    @ApiOperation(value = "根据企业查询气味(轮廓图)", httpMethod = "GET", response = SourceOdor.class)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "enterpriseName", value = "企业名称", paramType = "query", dataType = "Integer", required = true)
    })
    public Result getOdorsByEnterprise(@RequestParam(value = "enterpriseName", required = true) String enterpriseName) {
        SourceEnterpriseVo vo = new SourceEnterpriseVo();
        // 获取企业下的所有污染源
        SourceEnterprise enterprises = sourceEnterpriseService.getOne(new LambdaQueryWrapper<SourceEnterprise>()
                .eq(SourceEnterprise::getSourceName, enterpriseName));
        vo.setSourceEnterprise(enterprises);
        List<Source> sources = sourceService.list(new LambdaQueryWrapper<Source>()
                .in(Source::getEnterpriseId, enterprises.getId()));

        vo.setSources(sources);
        List<SourceOdor> odors = odorService.list(new LambdaQueryWrapper<SourceOdor>()
                .eq(SourceOdor::getSiteName, enterprises.getSourceCode()));
        vo.setOdors(odors);
        List<String> odorNames = odors.stream().map(SourceOdor::getOdorName).distinct().collect(Collectors.toList());
        LambdaQueryWrapper<Material> queryWrapper = new LambdaQueryWrapper<>();
        for (String name : odorNames) {
            queryWrapper.or(wrapper -> wrapper.like(Material::getOdorCharacteristics, name));
        }
        List<Material> materials = materialService.list(queryWrapper);
        vo.setMaterials(materials);
        Map<String, Map<String,List<String>>> odorMaterials = new HashMap<>();
        for (String name : odorNames) {
           List<Material> odorMaterial =  materials.stream().filter(m -> m.getOdorCharacteristics().contains(name)).collect(Collectors.toList());
           Map<String,List<Material>> map =odorMaterial.stream().collect(Collectors.groupingBy(Material::getMaterialType));
           Map<String,List<String>> materialTypes = new HashMap<>();
           // 物质种类，物质名称
           map.forEach((k,v)->{
               List<String> materialNames = v.stream().map(Material::getMaterialName).collect(Collectors.toList());
               materialTypes.put(k,materialNames);
           });
            odorMaterials.put(name,materialTypes);
        }
        vo.setOdorMaterials(odorMaterials);
        return Result.ok(vo);
    }

    @GetMapping("/odor/active/sites")
    @ApiOperation(value = "因子识别-气味活动活度值分析", httpMethod = "GET", response = SourceOdor.class)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "siteIds", value = "点位ID集合，用逗号隔开", paramType = "query", dataType = "siteIds", required = true)
    })
    public Result<List<SiteMaterial>> odorActive(@RequestParam(value = "siteIds", required = true) String siteIds) {
        List<Source> sources = sourceService.list(new LambdaQueryWrapper<Source>().in(Source::getId, Arrays.stream(siteIds.split(",")).collect(Collectors.toList())));
        if (sources.isEmpty())
            return Result.fail("点位ID为空！");
        List<SiteMaterial> voList = sampleService.getSiteMaterials(sources.stream().map(Source::getSiteName).collect(Collectors.toList()));
        Map<String, List<SiteMaterial>> map = voList.stream().filter(s->s.getOav()!=null&&s.getOav() > 0.1).collect(Collectors.groupingBy(SiteMaterial::getMaterialName));
        List<SiteMaterial> res = new ArrayList<>();
        map.forEach((k,v)->{
            v.sort((o1, o2) -> o2.getMaxConcentration().compareTo(o1.getMaxConcentration()));
            res.add(v.get(0));
        });
        res.sort((o1, o2) -> o2.getConcentration().compareTo(o1.getConcentration()));
        return Result.ok(res);
    }

    @GetMapping("/sits/calMathDegree")
    @ApiOperation(value = "因子识别-计算匹配度", httpMethod = "GET", response = SourceOdor.class)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "siteIds", value = "点位ID集合，用逗号隔开", paramType = "query", dataType = "siteIds", required = true),
            @ApiImplicitParam(name = "sampleId", value = "受体（敏感点）ID", paramType = "query", dataType = "sampleId", required = true),
    })
    public Result<List<SiteMatchDegree>> calMathDegree(@RequestParam(value = "siteIds", required = true) String siteIds,
                                                    @RequestParam(value = "sampleId", required = true) Integer sampleId){
        List<Source> sources = sourceService.list(new LambdaQueryWrapper<Source>().in(Source::getId, Arrays.stream(siteIds.split(",")).collect(Collectors.toList())));
        if (sources.isEmpty())
            return Result.fail("点位ID为空！");
        List<SiteMaterial> voList = sampleService.getSiteMaterials(sources.stream().map(Source::getSiteName).collect(Collectors.toList()));
        Map<String, List<SiteMaterial>> map1 = voList.stream().collect(Collectors.groupingBy(SiteMaterial::getSiteName));
        List<SampleDetail> list = sampleDetailService.list(new LambdaQueryWrapper<SampleDetail>()
                .eq(SampleDetail::getSampleId,sampleId));

        Map<String, List<SampleDetail>> map2 = list.stream().filter(s->StrUtil.isNotBlank(s.getMaterialName())).collect(Collectors.groupingBy(SampleDetail::getMaterialName));
        List<String> materialNames = map2.keySet().stream().distinct().collect(Collectors.toList());
        double[] a = new double[materialNames.size()];
        for (int i = 0; i < materialNames.size(); i++) {
            a[i] = 0.0;
            if (map2.get(materialNames.get(i))!=null)
                a[i] = map2.get(materialNames.get(i)).get(0).getConcentration();
        }
        List<SiteMatchDegree> res = new ArrayList<>();
        map1.forEach((k,v)->{
            SiteMatchDegree degree = new SiteMatchDegree();
            degree.setSiteName(k);
            Map<String, List<SiteMaterial>> m = v.stream().collect(Collectors.groupingBy(SiteMaterial::getMaterialName));
            double[] b = new double[materialNames.size()];
            for (int i = 0; i < materialNames.size(); i++) {
                b[i] = 0.0;
                if (m.get(materialNames.get(i))!=null)
                    b[i] = m.get(materialNames.get(i)).get(0).getConcentration();
            }
            degree.setDegree(VectorUtils.calculator(a,b));
            res.add(degree);
        });
        return Result.ok(res);
    }
}